Binary Search Tree

- Search
- Minimum
- Maximum
- Predecessor
- Successor
- Insert
- Delete

트리 구조의 기본연산은 트리의 높이에 비례하는 시간에 수행된다.(lgn)
Binary Search Tree
- key
- satellite data
- left, right, p
Binary Search Tree Property x를 이진 검색 트리의 한 노드라고 할 때, y가 x의 왼쪽 서브 트리의 한 노드이면 y.keyx.key y가 x의 오른쪽 서브 트리의 한 노드이면 y.keyx.key 를 만족한다.
이진 검색 트리는 중위 트리 순회(inorder tree walk) 재귀 알고리즘을 통해
이진 검색 트리의 모든 키를 정렬된 순서대로 출력할 수 있다.

- 중위 트리 순회(inorder tree walk)
- 전위 트리 순회(preorder tree walk)
- 후위 트리 순회(postorder tree walk)
#include <iostream>
using namespace std;
template <typename T>
struct Node{
T key, value;
Node *p=nullptr, *left=nullptr, *right=nullptr;
Node(T _key, T _value): key(_key), value(_value) {}
};
template <typename T>
class BinaryTree{
public:
BinaryTree(){}
Node<T>* Root(void){
return this->root;
}
void InorderTreeWalk(Node<T>* x){
if(x!=nullptr){
InorderTreeWalk(x->left);
cout<<x->key<<endl;
InorderTreeWalk(x->right);
}
}
Node<T>* Search(Node<T>* x, T key){
if(x==nullptr || key==x->key) return x;
if(key<x->key) return Search(x->left, key);
else return Search(x->right, key);
}
Node<T>* IterativeSearch(Node<T>* x, T key){
while(x!=nullptr && key!=x->key){
if(key<x->key) x=x->left;
else x=x->right;
}
return x;
}
Node<T>* Minimum(Node<T>* x){
while(x->left!=nullptr) x=x->left;
return x;
}
Node<T>* Maximum(Node<T>* x){
while(x->right!=nullptr) x=x->right;
return x;
}
Node<T>* Successor(Node<T>* x){
if(x->right!=nullptr) return Minimum(x->right);
Node<T>* y=x->p;
while(y!=nullptr && x==y->right){
x=y;
y=y->p;
}
return y;
}
void Insert(int key, int value){
Node<T>* z=new Node(key, value);
Node<T> *x, *y;
x=this->root; y=nullptr;
while(x!=nullptr){
y=x;
if(z->key<x->key) x=x->left;
else x=x->right;
}
z->p=y;
if(y==nullptr) this->root=z;
else if(z->key<y->key) y->left=z;
else y->right=z;
}
void Transplant(Node<T>* u, Node<T>* v){
if(u->p==nullptr) this->root=v;
else if(u==u->p->left) u->p->left=v;
else u->p->right=v;
if(v!=nullptr) v->p=u->p;
}
void Delete(int key){
Node<T>* z=Search(this->root, key);
if(z->left==nullptr) Transplant(z, z->right);
else if(z->right==nullptr) Transplant(z, z->left);
else {
Node<T>* y=Minimum(z->right);
if(y->p!=z){
Transplant(y, y->right);
y->right=z->right;
y->right->p=y;
}
Transplant(z, y);
y->left=z->left;
y->left->p=y;
}
delete z;
}
private:
Node<T>* root=nullptr;
};
int main(void){
BinaryTree<int> tree;
tree.Insert(12, 12);
tree.Insert(5, 5);
tree.Insert(2, 2);
tree.Insert(9, 9);
tree.Insert(18, 18);
tree.Insert(15, 15);
tree.Insert(19, 19);
tree.Insert(13, 13);
tree.Insert(17, 17);
cout<<tree.Maximum(tree.Root())->value<<endl;
tree.Delete(19);
cout<<tree.Maximum(tree.Root())->value<<endl;
return 0;
}
삽입과 삭제는 동적 집합을 변화시킨다.
이 때도 이진 검색 트리 특성을 계속 유지해야 한다.

이진 트리는 단순 증가 순열이 삽입될 경우, 연결 리스트와 같은 구조로 형성된다(높이 n-1)
n개의 서로 다른 키를 갖는 임의로 만들어진 이진 탐색 트리의 높이의 기대값은 O(lgn)이다.
기수 트리
문자열 비교(lexicographically less than; 사전적으로 더 작다)
a=a0a1...ap & b=b0b1...bq
인 경우, 다음을 만족할 때, a가 문자열 b보다 작다고 정의
1. 0jmin(p,q)인 정수 j가 존재해 모든 i=0, 1, ..., j-1에 대해 ai=bi이고 aj<bj인 경우 2. p<q 이고 모든 i=0, 1, ... ,p에 대해 ai=bi 인 경우
이진 트리가 각각 비트 0, 1로 분할될 경우, 문자열에 대해 이진 트리 특성을 만족하도록 만들 수 있다.